home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 46
/
Amiga Format CD46 (1999-10-20)(Future Publishing)(GB)[!][issue 1999-12].iso
/
-in_the_mag-
/
synth_studies
/
soundzapv3
/
soundzap.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-15
|
27KB
|
1,007 lines
/************/
/**SoundZAP**/
/************/
/*
* This program was compiled with Matthew Dillon's DICE C compiler, which
* automatically opens and closes the Amiga libraries as they are needed.
* If your compiler does not do this you will have to Add the appropriate
* code (or get DICE!!).
*/
#include "SoundZAP.h"
void main(int argc, char *argv[])
{
char comline[33];
struct options *Opt;
if (argc<2) GiveUsage();
printf(SZVER);
printf(" -- 3 June 1992 -- (c) Michael Cramer\n\n");
if ((Opt=(struct options *)malloc(sizeof(struct options)))==NULL)
CleanUp(Opt,5);
Opt->BuffSize = DEFAULT_SIZE;
Opt->Size = 0;
Opt->InSign = TRUE;
Opt->OutSign = TRUE;
Opt->KillChunk = FALSE;
Opt->FibDeltIn = FALSE;
Opt->MuLawIn = FALSE;
Opt->MuLawOut = FALSE;
Opt->SampRate = 0;
Opt->NewRate = 0;
Opt->Data = NULL;
Opt->Amp = 3;
Opt->Bits = 8;
Opt->InType = UNKNOWN;
Opt->OutType = IFF;
Opt->inname[0] = '\0';
Opt->outname[0] = '\0';
Opt->FileName[0] = '\0';
Opt->Auth = NULL;
Opt->Copy = NULL;
while (--argc > 0)
{
strcpy(comline,argv[argc]);
if (comline[0]=='-')
ProcessOpt(Opt,comline);
else
{
strcpy(Opt->outname,Opt->inname);
strcpy(Opt->inname,comline);
}
}
if (strlen(Opt->inname)==0)
GiveUsage();
if (strlen(Opt->outname)==0)
{
int l;
strcpy(Opt->outname,Opt->inname);
l=strlen(Opt->outname);
if(Opt->outname[l-4]=='.')
Opt->outname[l-4]='\0';
if(Opt->outname[l-3]=='.')
Opt->outname[l-3]='\0';
AFlag=TRUE;
}
else
AFlag=FALSE;
strcpy(Opt->FileName,Opt->outname);
AnalyzeData(Opt);
CleanUp(Opt,0);
}
void GiveUsage()
{
printf(SZVER);
printf("\nUsage: SoundZAP [<options>] SOURCE [DESTINATION]\n");
printf(" (actually, the options can appear anywhere)\n\n");
printf(" options -a<n> Amplify by n/3 times\n");
printf("\t\t-b<n> Use a buffer size of n kilobytes\n");
printf("\t\t-c<n> Physically resample data to n\n");
printf("\t\t-f Assume input data is RAW\n");
printf("\t\t-l Output u-lawed data\n");
printf("\t\t-n Don't create extra chunks in IFF output\n");
printf("\t\t-r<n> Change sample rate to n\n");
printf("\t\t-s Output a Sun .au file\n");
printf("\t\t-u Output UNSIGNED data\n");
printf("\t\t-w Output RAW data\n");
printf("\nSee documentation for more info.\n");
printf("mrc113@psuvm.psu.edu\n");
exit(0);
}
void ProcessOpt(struct options *Opt, char com[])
{
int len;
switch (com[1])
{
case 'a' : len=strlen(com)-2;
if (len==0)
Opt->Amp=0;
Opt->Amp=(UBYTE)atoi(com+2);
break;
case 'b' : len=strlen(com)-2;
if (len==0)
Opt->BuffSize=0;
Opt->BuffSize=(ULONG)atoi(com+2)*1024;
break;
case 'c' : Opt->NewRate = GetRateFromString(Opt, com+2);
break;
case 'f' : Opt->InType=RAW;
break;
case 's' : Opt->OutType=AU;
Opt->MuLawOut=TRUE;
Opt->NewRate=8000;
break;
case 'w' : Opt->OutType=RAW;
break;
case 'l' : Opt->MuLawOut=TRUE;
break;
case 'n' : Opt->KillChunk=TRUE;
break;
case 'r' : Opt->SampRate = GetRateFromString(Opt, com+2);
break;
case 'u' : Opt->OutSign=FALSE;
break;
default : CleanUp(Opt,4);
}
}
UWORD GetRateFromString(struct options *Opt, char *c)
{
int len;
UWORD n;
len=strlen(c);
if (len==0)
CleanUp(Opt,3);
if (len==1)
{
switch (c[0])
{
case '5' : n=5696;
break;
case '7' : n=7596;
break;
case '8' : n=8000;
break;
case '2' : n=22790;
break;
default : n=11395;
}
}
else
{
n=(UWORD)atoi(c);
if (!n) n=11395;
}
return n;
}
void CleanUp(struct options *Opt, int Error)
{
if (Opt->Data) free(Opt->Data);
if (Opt->Auth) free(Opt->Auth);
if (Opt->Copy) free(Opt->Copy);
if (Opt) free(Opt);
if (in) Close(in);
if (out) Close(out);
if (Error==0) exit(0);
else
{
printf("%s",ErrorMessages[Error]);
exit(20);
}
}
void AnalyzeData(struct options *Opt)
{
ULONG MagicWord;
char IsMac[8];
if ((in=(struct FileHandle *)Open(Opt->inname,MODE_OLDFILE))==NULL)
CleanUp(Opt,6);
if(Opt->BuffSize==0)
{
Seek(in,0,OFFSET_END);
Opt->BuffSize = (Seek(in,0,OFFSET_BEGINNING) + 1) & ~1;
}
if ((Opt->Data=(BYTE *)malloc(Opt->BuffSize))==NULL)
CleanUp(Opt,5);
Read(in,&MagicWord,4);
if (Opt->InType==UNKNOWN)
{
if (MagicWord==0x2e736e64) /* '.snd' */
ConvertAU(Opt);
else if (MagicWord==0x464f524d) /* 'FORM' */
ConvertIFF(Opt);
else if (MagicWord==0x43726561) /* 'Crea' */
ConvertVOC(Opt);
else if (MagicWord==0x52494646) /* 'RIFF' */
ConvertWAV(Opt);
else
{
Seek(in,65,OFFSET_BEGINNING);
Read(in,IsMac,8);
if (!strcmp(IsMac,"FSSDSFX!"))
ConvertMAC(Opt);
else
GuidoCheck(Opt);
}
}
ConvertRaw(Opt);
}
/* This routine is a modified version of Guido van Rossum's (guido@cwi.nl)
* 'whatsound' routine. It guesses the sound file type (signed/unsigned/u-law)
* by checking how the values in the file are distributed. Thanks Guido!!
*/
void GuidoCheck(struct options *Opt)
{
LONG a,n;
ULONG bin[4];
int x;
Opt->InType=RAW;
for (a=0; a<4; a++)
bin[a]=0;
do
{
n=Read(in,Opt->Data,Opt->BuffSize);
for(a=0; a<n; a++)
bin[(UBYTE)Opt->Data[a]/64]++;
}
while (n==Opt->BuffSize);
if((bin[2]==0) && (bin[3]==0))
CleanUp(Opt,7);
x=((bin[0]+bin[3])*100)/(bin[1]+bin[2]);
if(x>=300)
Opt->InSign=TRUE;
else if ( x <= 33)
Opt->InSign=FALSE;
else if ( (x >= 50) && (x <= 200))
{
Opt->MuLawIn=TRUE;
if(Opt->SampRate==0) Opt->SampRate=8000;
}
if(!Opt->SampRate)
Opt->SampRate=11395;
Seek(in,0,OFFSET_END);
Opt->Size=Seek(in,0,OFFSET_BEGINNING);
}
void ConvertRaw(struct options *Opt)
{
LONG b_read,i,scale,b_written,total,t,BuffSize;
int max;
signed char logs[256];
unsigned char ulawbytes[256];
BPTR op=Output();
BYTE max2=0, *Data, x;
if(AFlag)
switch (Opt->OutType)
{
case IFF : strcat(Opt->outname,".iff");
break;
case RAW : strcat(Opt->outname,".raw");
break;
case AU : strcat(Opt->outname,".au");
break;
default : strcat(Opt->outname,".out");
}
if((out=(struct FileHandle *)Open(Opt->outname,MODE_NEWFILE))==NULL)
CleanUp(Opt,8);
if (Opt->MuLawIn && (!Opt->MuLawOut))
{
Opt->Amp=3;
max=getscale(Opt);
maketable(logs,max);
if (Opt->InType==AU)
Seek(in,32,OFFSET_BEGINNING);
else
Seek(in,0,OFFSET_BEGINNING);
}
if (Opt->MuLawOut && (!Opt->MuLawIn))
maketableII(ulawbytes);
scale=Opt->Bits/8;
if (!Opt->Amp)
{
LONG tmppos;
BYTE a;
total=0;
tmppos=Seek(in,0,OFFSET_CURRENT);
do
{
b_read=Read(in,Opt->Data,Opt->BuffSize)/scale;
for(i=0; i<b_read; i++)
max2=MAX(max2,Opt->Data[i*scale]);
total+=b_read;
}
while (total < Opt->Size);
Seek(in,tmppos,OFFSET_BEGINNING);
}
if(Opt->NewRate)
Opt->Size = Opt->Size * Opt->NewRate / Opt->SampRate;
PrintIOInfo(Opt);
switch (Opt->OutType)
{
case IFF : WriteIFFStuff(Opt); break;
case AU : WriteAUStuff(Opt); break;
}
if ( Opt->FibDeltIn )
{
BuffSize = Opt->BuffSize >> 1;
Data = Opt->Data + BuffSize;
Read (in, &x, 1);
Read (in, &x, 1);
}
else
{
BuffSize = Opt->BuffSize;
Data = Opt->Data;
}
total=0;
do
{
b_read=Read(in, Data, BuffSize)/scale;
if (Opt->FibDeltIn)
{
x = D1Unpack(Data,b_read,Opt->Data,x);
b_read <<= 1;
}
if(Opt->MuLawIn && (!Opt->MuLawOut))
for (i=0; i<b_read; i++)
Opt->Data[i]=logs[(UBYTE)Opt->Data[i]];
else
{
if(scale!=1)
for (i=0; i<b_read; i++)
Opt->Data[i]=Opt->Data[i*scale];
if(Opt->Amp && (Opt->Amp!=3))
for (i=0; i<b_read; i++)
Opt->Data[i]=Opt->Amp*Opt->Data[i]/3;
else if((Opt->Amp==0) && (max2 != 127))
for (i=0; i<b_read; i++)
Opt->Data[i]=Opt->Data[i]*127/max2;
}
if(Opt->NewRate)
{
for(t=0; t<(b_read * Opt->NewRate / Opt->SampRate); t++)
Opt->Data[t]=Opt->Data[t * Opt->SampRate / Opt->NewRate];
b_read = b_read * Opt->NewRate / Opt->SampRate;
}
if(Opt->InSign != Opt->OutSign)
for (i=0; i<b_read; i++)
Opt->Data[i] ^= 0x80;
if(Opt->MuLawOut && (!Opt->MuLawIn))
for (i=0; i<b_read; i++)
Opt->Data[i] = ulawbytes[(unsigned char)Opt->Data[i]];
total+=b_read;
b_written=Write(out,Opt->Data,b_read);
FileLen+=b_written;
if(b_written!=b_read) CleanUp(Opt,10);
}
while((total < Opt->Size) && (b_read > 0));
if((Opt->OutType == IFF) && (total & 1))
FileLen+=Write(out,'\0',1);
if(Opt->OutType == IFF)
FixSize(Opt, total);
CleanUp(Opt,0);
}
void FixSize(struct options *Opt, ULONG total)
{
FileLen-=8;
Seek(out,4,OFFSET_BEGINNING);
Write(out,&FileLen,4);
Seek(out,BodySpot+4,OFFSET_BEGINNING);
Write(out,&total,4);
Seek(out,20,OFFSET_BEGINNING);
Write(out,&total,4);
}
void WriteIFFStuff(struct options *Opt)
{
ULONG i;
ChunkHeader Head;
time_t t;
struct tm *tp;
char datetime[50];
Voice8Header V8H = {0,0,32,8363,1,0,Unity};
Head.ckID = FORM;
Head.ckSize = 0;
FileLen+=Write(out,&Head,8);
i=ID_8SVX;
FileLen+=Write(out,&i,4);
Head.ckID = ID_VHDR;
Head.ckSize = 20;
FileLen+=Write(out,&Head,8);
V8H.oneShotHiSamples = 0;
V8H.samplesPerSec = Opt->NewRate ? Opt->NewRate : Opt->SampRate;
FileLen+=Write(out,&V8H,20);
if (!Opt->KillChunk)
{
i=strlen(Opt->FileName);
printf("NAME: %s\n",Opt->FileName);
Head.ckID = ID_NAME;
Head.ckSize = i;
FileLen+=Write(out,&Head,8);
FileLen+=Write(out,Opt->FileName,i);
FileLen+=Write(out,'\0',i & 1);
if(!Opt->Auth)
{
if(!(Opt->Auth=(char *)malloc(strlen(SZVER)+25)))
CleanUp(Opt,5);
strcpy(Opt->Auth,SZVER);
strcat(Opt->Auth," by mrc113@psuvm.psu.edu");
}
i=strlen(Opt->Auth);
printf("AUTH: %s\n",Opt->Auth);
Head.ckID = ID_AUTH;
Head.ckSize = i;
FileLen+=Write(out,&Head,8);
FileLen+=Write(out,Opt->Auth,i);
FileLen+=Write(out,'\0',i & 1);
t=time(NULL);
tp=localtime(&t);
i=strftime(datetime,49,"Converted: %d %b %Y %X by SoundZAP",tp);
printf("ANNO: %s\n",datetime);
Head.ckID = ID_ANNO;
Head.ckSize = i;
FileLen+=Write(out,&Head,8);
FileLen+=Write(out,datetime,i);
FileLen+=Write(out,'\0',i & 1);
if(strlen(Opt->Copy))
{
i=strlen(Opt->Copy);
printf("Copyright: %s\n",Opt->Copy);
Head.ckID = ID_Copyright;
Head.ckSize = i;
FileLen+=Write(out,&Head,8);
FileLen+=Write(out,Opt->Copy,i);
FileLen+=Write(out,'\0',i & 1);
}
}
BodySpot=Seek(out,0,OFFSET_CURRENT);
Head.ckID = ID_BODY;
Head.ckSize = 0L;
FileLen+=Write(out,&Head,8);
}
void WriteAUStuff(struct options *Opt)
{
AUHeader AUH;
AUH.magic=0x2e736e64; /* '.snd' */
AUH.hrd_size=24;
AUH.channels=1;
AUH.sample_rate=8000;
Opt->NewRate=8000;
AUH.encoding=1;
AUH.data_size=0;
FileLen+=Write(out,&AUH,24);
}
void PrintIOInfo(struct options *Opt)
{
printf("\n%s -> %s\n\n",Opt->inname,Opt->outname);
printf("Convert from ");
switch (Opt->InType)
{
case IFF : printf("IFF 8SVX to "); break;
case AU : printf(".au to "); break;
case RAW : printf("Raw data to "); break;
case AIFF : printf("AIFF to "); break;
case VOC : printf(".voc to "); break;
case WAV : printf(".wav to "); break;
case MAC : printf("Macintosh to "); break;
default : printf(" <UNKNOWN> to ");
}
switch (Opt->OutType)
{
case IFF : printf("IFF 8SVX\n"); break;
case AU : printf(".au\n"); break;
case RAW : printf("Raw data\n"); break;
/*
case AIFF : printf("AIFF\n"); break;
case VOC : printf(".voc\n"); break;
case WAV : printf(".wav\n"); break;
case MAC : printf("Macintosh\n"); break;
*/
default : printf(" <UNKNOWN>\n");
}
printf("\nInput data is ");
if(Opt->MuLawIn)
printf("u-lawed, ");
else
printf(Opt->InSign ? "signed, " : "unsigned, ");
if (Opt->FibDeltIn) printf("Fibonacci Delta encoded, ");
printf("and the output data is ");
if(Opt->MuLawOut)
printf("u-lawed\n");
else
printf(Opt->OutSign ? "signed\n" : "unsigned\n");
printf("Input data is %d bits per sample, %d samples per second\n",Opt->Bits,Opt->SampRate);
if (Opt->NewRate)
printf("Output data is re-sampled to %d samples per second\n",Opt->NewRate);
printf("\nBuffer size: %d bytes\n",Opt->BuffSize);
if(!Opt->Amp)
printf("\nOutput data amplified to maximum\n");
else if (Opt->Amp != 3)
printf("\nOutput data amplified %d thirds times\n",Opt->Amp);
if(Opt->OutType == IFF)
if(Opt->KillChunk) printf("\nSuppress extra chunk creation\n");
else printf("\nChunks to be written to IFF file:\n");
}
void ConvertVOC(struct options *Opt)
{
UBYTE c[2];
if(!Opt->SampRate)
{
Seek(in,30,OFFSET_BEGINNING);
Read(in,c,2);
if(c[1]!=0)
CleanUp(Opt,9);
Opt->SampRate=1000000/(256-c[0]);
}
Opt->InSign=FALSE;
Seek(in,0,OFFSET_END);
Opt->Size=Seek(in,0,OFFSET_BEGINNING)-32;
Seek(in,32,OFFSET_BEGINNING);
Opt->InType=VOC;
}
void ConvertWAV(struct options *Opt)
{
ChunkHeader Head;
ULONG FileSize;
ULONG FileType;
LONG b_read;
WaveFmtChunk fmt;
Seek(in,0,OFFSET_BEGINNING);
Read(in,&Head,8);
if(Head.ckID != RIFF)
CleanUp(Opt,12);
FileSize = SCREWINTEL(Head.ckSize);
b_read=Read(in,&FileType,4);
if(FileType != WAVE)
CleanUp(Opt,12);
while((Head.ckID != DATA) && b_read)
{
b_read = Read(in,&Head,8);
if (b_read)
{
Head.ckSize = SCREWINTEL(Head.ckSize);
if (Head.ckID == FMT)
{
Read(in,&fmt,sizeof(WaveFmtChunk));
if(fmt.wChannels != 0x0100)
CleanUp(Opt,15);
if(fmt.wFormatTag != 0x0100)
CleanUp(Opt,9);
Opt->SampRate = SCREWINTEL(fmt.dwSamplesPerSec);
Seek(in,Head.ckSize - sizeof(WaveFmtChunk),OFFSET_CURRENT);
}
else if (Head.ckID == DATA)
Opt->Size = SCREWINTEL(Head.ckSize);
else
Seek(in,(SCREWINTEL(Head.ckSize) + 1) & ~1 ,OFFSET_CURRENT);
}
}
Opt->InSign=FALSE;
Opt->InType=WAV;
}
void ConvertMAC(struct options *Opt)
{
USHORT len;
char *name;
Opt->InSign=FALSE;
Seek(in,0,OFFSET_END);
Opt->Size=Seek(in,0,OFFSET_BEGINNING)-668;
Read(in,&len,2);
name=(char *)malloc(len);
Read(in,name,len);
name[len]='\0';
strcpy(Opt->FileName,name);
Seek(in,128,OFFSET_BEGINNING);
if (!Opt->SampRate)
Opt->SampRate=11395;
free(name);
Opt->InType=MAC;
}
/* Thanks to Sean Connolly for sending me info on the .au sound format.*/
void ConvertAU(struct options *Opt)
{
AUHeader AUHdr;
Seek(in,0,OFFSET_END);
Opt->Size=Seek(in,0,OFFSET_BEGINNING)-32;
Read(in,&AUHdr,28);
switch (AUHdr.encoding)
{
case 1 : Opt->MuLawIn=TRUE;
break;
case 2 : Opt->Bits=8;
break;
case 3 : Opt->Bits=16;
Opt->Size/=2;
break;
case 4 : Opt->Bits=24;
Opt->Size/=3;
break;
case 5 : Opt->Bits=32;
Opt->Size/=4;
break;
default : CleanUp(Opt,9);
break;
}
if (!Opt->SampRate)
Opt->SampRate=AUHdr.sample_rate;
Opt->InType=AU;
}
void ConvertIFF(struct options *Opt)
{
struct ChunkInfo List, *This, *Next;
Voice8Header V8H;
CommonChunk CC;
char *data;
int Help=0;
BOOL Flag=TRUE;
List=GetChunks(Get,9,in);
if (List.Next == NULL)
Help=11;
else
{
switch(List.Name)
{
case ID_8SVX : Opt->InType=IFF; break;
case ID_AIFF : Opt->InType=AIFF; break;
default : Help=11;
}
}
Next=List.Next;
while(Next)
{
This=Next;
Seek(in,This->Pos,OFFSET_BEGINNING);
switch(This->Name)
{
case ID_COMM : Read(in,&CC,18);
Opt->Size=CC.numSampleFrames;
Opt->Bits=(CC.sampleSize+7)/8;
Opt->Bits*=8;
break;
case ID_SSND : Seek(in,8,OFFSET_CURRENT); /*Don't use it for anything so just get to the right place */
break;
case ID_VHDR : Read(in,&V8H,20);
if (!Opt->SampRate)
Opt->SampRate=V8H.samplesPerSec;
if(V8H.sCompression) Opt->FibDeltIn=TRUE;
break;
case ID_BODY : Opt->Size=This->Size;
break;
/* AUTH and Copyright must be preserved! */
case ID_AUTH : if(!(Opt->Auth=(char *)malloc(This->Size)))
CleanUp(Opt,5);
Read(in,Opt->Auth,This->Size);
Opt->Auth[This->Size]='\0';
if (!strncmp(Opt->Auth,"SoundZAP",8))
{
free(Opt->Auth);
Opt->Auth=NULL;
}
break;
case ID_Copyright : if(!(Opt->Copy=(char *)malloc(This->Size)))
CleanUp(Opt,5);
Read(in,Opt->Copy,This->Size);
Opt->Copy[This->Size]='\0';
break;
case ID_NAME : if(!(data=(char *)malloc(This->Size)))
CleanUp(Opt,5);
Read(in,data,This->Size);
data[This->Size]='\0';
if (Flag) printf("Chunks found but not preserved:\n");
printf("NAME: %s\n",data);
free(data);
Flag=FALSE;
break;
case ID_ANNO : if(!(data=(char *)malloc(This->Size)))
CleanUp(Opt,5);
Read(in,data,This->Size);
data[This->Size]='\0';
if (Flag) printf("Chunks found but not preserved:\n");
Flag=FALSE;
printf("ANNO: %s\n",data);
free(data);
break;
case ID_TEXT : if(!(data=(char *)malloc(This->Size)))
CleanUp(Opt,5);
Read(in,data,This->Size);
data[This->Size]='\0';
if (Flag) printf("Chunks found but not preserved:\n");
Flag=FALSE;
printf("TEXT: %s\n",data);
free(data);
break;
}
Next=This->Next;
free(This);
}
if (Help)
CleanUp(Opt,Help);
}
/*--------------------------------------------------------------------------*
* The following routine was extracted from posting by Brian Foley. *
* Brian Foley email: bfoley@greatlakes.Central.Sun.COM *
* Systems Engineer smail: 1000 Town Center *
* Sun Microsystems Suite 1700 *
* GreatLakes Region Southfield, MI 48075 (313) 352-7070 *
*--------------------------------------------------------------------------*/
int ulaw2linear(unsigned char ulawbyte)
{
static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
int sign, exponent, mantissa, sample;
ulawbyte = ~ulawbyte;
sign = ulawbyte & 0x80;
exponent = (ulawbyte >> 4) & 0x07;
mantissa = ulawbyte & 0x0F;
sample = (exp_lut[exponent] + (mantissa << (exponent + 3)));
if ( sign ) sample = -sample;
return sample;
}
int getscale(struct options *Opt)
{
int count, max = 0, i;
do
{
count = Read(in, Opt->Data, Opt->BuffSize);
for ( i = 0; i < count; i++ )
max = MAX(abs(ulaw2linear(Opt->Data[i])), max);
}
while ( count == Opt->BuffSize );
return max;
}
void maketable(signed char *logs, int max)
{
int i, c, d;
for ( i = 0; i < 256; i++ )
{
c = ( ulaw2linear(i) * ulaw2linear(0) ) / max;
d = abs(c) & 0xFF;
if ( d > 0x7F )
if ( c > 0 )
logs[i] = (signed char) ( c / 256 + 1 );
else
logs[i] = (signed char) ( c / 256 - 1 );
else
logs[i] = (signed char) ( c / 256 );
}
}
void maketableII(unsigned char *ubytes)
{
signed int i;
for(i=0; i<256; i++)
ubytes[i]=st_linear_to_ulaw((signed char)i);
}
/*
** This routine converts from linear to ulaw.
**
** Craig Reese: IDA/Supercomputing Research Center
** Joe Campbell: Department of Defense
** 29 September 1989
**
** References:
** 1) CCITT Recommendation G.711 (very difficult to follow)
** 2) "A New Digital Technique for Implementation of Any
** Continuous PCM Companding Law," Villeret, Michel,
** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
** 1973, pg. 11.12-11.17
** 3) MIL-STD-188-113,"Interoperability and Performance Standards
** for Analog-to_Digital Conversion Techniques,"
** 17 February 1987
**
** Input: Signed 16 bit linear sample
** Output: 8 bit ulaw sample
*/
#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
#define CLIP 32635
unsigned char st_linear_to_ulaw( signed char oldsample )
{
static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
int sign, exponent, mantissa, sample;
unsigned char ulawbyte;
sample=oldsample << 8;
/* Get the sample into sign-magnitude. */
sign = (sample >> 8) & 0x80; /* set aside the sign */
if ( sign != 0 ) sample = -sample; /* get magnitude */
if ( sample > CLIP ) sample = CLIP; /* clip the magnitude */
/* Convert from 16 bit linear to ulaw. */
sample = sample + BIAS;
exponent = exp_lut[( sample >> 7 ) & 0xFF];
mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
/*
if ( ulawbyte == 0 ) ulawbyte = 0x02;
*/
return ulawbyte;
}
struct ChunkInfo GetChunks(ULONG *Names, int n, struct FileHandle *in)
{
LONG Size, pos=0,b_read;
ChunkHeader Head;
struct ChunkInfo List, *ThisNode;
ID Type;
int i;
Seek(in,0,OFFSET_END);
Size=Seek(in,0,OFFSET_BEGINNING);
if(Size < 50)
{
List.Size=ERROR_IN_FORM;
List.Next=NULL;
return List;
}
pos+=Read(in,&Head,8);
if (Head.ckID != FORM)
{
List.Size=ERROR_IN_FORM;
List.Next=NULL;
return List;
}
pos+=Read(in,&List.Name,4);
b_read=Read(in,&Head,8);
ThisNode=&List;
do
{
pos+=b_read;
for (i=1; i<n; i++)
if (Head.ckID == Names[i])
{
if((ThisNode->Next=(void *)malloc(16))==NULL)
{
List.Size=NO_MEMORY;
return List;
}
ThisNode=ThisNode->Next;
ThisNode->Next = NULL;
ThisNode->Name = Head.ckID;
ThisNode->Size = Head.ckSize;
ThisNode->Pos = pos;
}
Seek(in,Head.ckSize+(Head.ckSize & 1),OFFSET_CURRENT);
pos+=Head.ckSize+(Head.ckSize & 1);
b_read=Read(in,&Head,8);
}
while ((ThisNode->Name!=ID_BODY) && (b_read==8));
List.Size=GOOD_FILE;
return List;
}